Unit tests are very useful for checking how our app is working.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing JavaScript unit tests.
Watch How the Content is Served over the Network
We want to know how fast our content is served to users over the network.
To measure this, we can use tools like pingdom or Lighthouse.
They’re available as programs that we can add to our CI pipeline to ensure continuous monitoring.
They show us test results in various formats.
Stub Flaky and Slow Resources Like Backend APIs
If we’re running front end tests, then slow resources like back end APIs should be stubbed.
This way, we can run our front end tests as fast as possible.
We can stub them with various libraries.
This lets us simulate various API behaviors so that we can provide the required data for our front end.
Without the stubbed data, the tests will be slow and reliable.
For instance, we can write a test like:
test("show message when product doesn't exist", () => {
nock("api")
.get(`/products`)
.reply(404);
const { getByTestId } = render(<ProductsList />);
expect(getByTestId("no-products-message")).toBeTruthy();
});
We stubbed the API call with nock
so that we don’t have to make the actual API call.
Have a Few End-to-End Tests that Spans the Whole System
We should have only a few end to end tests that span the whole system.
They’re slow and so they should be reserved for testing the most critical parts of our system.
They simulate real user interaction so that we know that they’re acting right with user interaction.
They’re also brittle so it’s hard to run many of them.
Also, they should run in a production-like environment so that they’re testing something realistic.
Speed-up E2E tests by Reusing Login Credentials
We should just log in once and then do all our tests.
Logging in takes extra time so we should leave that for the beginning.
We can put the login code into a before all hook so that it runs before all tests are run.
Any records associated with the user should be generated with the tests.
We can save the auth token with Cypress, for example:
let authenticationToken;
before(() => {
cy.request('POST', 'http://localhost:8888/login', {
username: Cypress.env('username'),
password: Cypress.env('password'),
})
.its('body')
.then((res) => {
authenticationToken = res.token;
})
})
beforeEach(setUser => () {
cy.visit('/profile', {
onBeforeLoad (win) {
win.localStorage.setItem('token', JSON.stringify(authenticationToken))
},
})
})
We get the username and password from the environment variables.
Then we log in with it and get the token by using the API instead of the GUI.
Then we get the token and use that before each test.
E2E Smoke Test that Just Travels Across the Site Map
End to end tests that just travel across the site makes sure that all parts of our site are working.
It’s easy to maintain and can find out any functional, network, or deployment issues.
Other kinds of smoke tests aren’t as reliable or exhaustive.
With Cypress, we can write:
it("can go to different pages", () => {
cy.visit("https://example.com/home");
cy.contains("Home");
cy.contains("https://example.com/profile");
cy.contains("Profile");
cy.contains("https://example.com/about");
cy.contains("About");
});
Conclusion
We can add various kinds of tests to test performance and smoke testing.